package com.teamide.util;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Serializable;
import java.io.Writer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;

public class IOUtil {

	/** 默认缓存大小 */
	public static final int DEFAULT_BUFFER_SIZE = 1024;

	public static final String DEFAULT_CHARSET = "UTF-8";

	public static final Charset CHARSET_UTF_8 = Charset.forName("UTF-8");

	/** 数据流末尾 */
	public static final int EOF = -1;

	public static void close(AutoCloseable... closeables) {

		if (null == closeables) {
			return;
		}
		for (AutoCloseable closeable : closeables) {
			if (null == closeable) {
				continue;
			}
			try {
				closeable.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 获得一个Writer
	 * 
	 * @param out
	 *            输入流
	 * @param charsetName
	 *            字符集
	 * @return OutputStreamWriter对象
	 */
	public static OutputStreamWriter getWriter(OutputStream out, String charsetName) {

		return getWriter(out, Charset.forName(charsetName));
	}

	/**
	 * 获得一个Writer
	 * 
	 * @param out
	 *            输入流
	 * @param charset
	 *            字符集
	 * @return OutputStreamWriter对象
	 */
	public static OutputStreamWriter getWriter(OutputStream out, Charset charset) {

		if (null == out) {
			return null;
		}

		if (null == charset) {
			return new OutputStreamWriter(out);
		} else {
			return new OutputStreamWriter(out, charset);
		}
	}

	public static byte[] read(InputStream stream) throws IOException {

		if (null == stream) {
			return null;
		}
		ByteArrayOutputStream result = null;
		try {
			result = new ByteArrayOutputStream();
			byte[] buffer = new byte[1024];
			int length;
			while ((length = stream.read(buffer)) != -1) {
				result.write(buffer, 0, length);
			}
			return result.toByteArray();
		} finally {
			close(result, stream);
		}
	}

	public static String readString(InputStream stream) throws IOException {

		return readString(stream, DEFAULT_CHARSET);
	}

	public static String readString(InputStream stream, String charset) throws IOException {

		if (null == stream) {
			return null;
		}
		if (StringUtil.isEmpty(charset)) {
			charset = DEFAULT_CHARSET;
		}
		return readString(stream, Charset.forName(charset));
	}

	public static String readString(InputStream stream, Charset charset) throws IOException {

		if (null == stream) {
			return null;
		}
		if (null == charset) {
			charset = Charset.forName(DEFAULT_CHARSET);
		}
		byte[] buffer = read(stream);
		if (buffer == null) {
			return null;
		}
		return new String(buffer, charset);
	}

	/**
	 * 从Reader中读取String，读取完毕后并不关闭Reader
	 * 
	 * @param reader
	 *            Reader
	 * @return String
	 * @throws IOException
	 *             IO异常
	 */
	public static String readString(Reader reader) throws IOException {

		final StringBuilder builder = new StringBuilder();
		final CharBuffer buffer = CharBuffer.allocate(DEFAULT_BUFFER_SIZE);
		try {
			while (-1 != reader.read(buffer)) {
				builder.append(buffer.flip().toString());
			}
		} finally {
			close(reader);
		}
		return builder.toString();
	}

	/**
	 * 将byte[]写到流中
	 * 
	 * @param out
	 *            输出流
	 * @param isCloseOut
	 *            写入完毕是否关闭输出流
	 * @param content
	 *            写入的内容
	 * @throws IOException
	 *             IO异常
	 */
	public static void write(OutputStream out, boolean isCloseOut, byte[] content) throws IOException {

		try {
			out.write(content);
		} finally {
			if (isCloseOut) {
				close(out);
			}
		}
	}

	/**
	 * 将多部分内容写到流中，自动转换为UTF-8字符串
	 * 
	 * @param out
	 *            输出流
	 * @param isCloseOut
	 *            写入完毕是否关闭输出流
	 * @param contents
	 *            写入的内容，调用toString()方法，不包括不会自动换行
	 * @throws IOException
	 *             IO异常
	 * @since 3.1.1
	 */
	public static void writeUtf8(OutputStream out, boolean isCloseOut, Object... contents) throws IOException {

		write(out, DEFAULT_CHARSET, isCloseOut, contents);
	}

	/**
	 * 将多部分内容写到流中，自动转换为字符串
	 * 
	 * @param out
	 *            输出流
	 * @param charsetName
	 *            写出的内容的字符集
	 * @param isCloseOut
	 *            写入完毕是否关闭输出流
	 * @param contents
	 *            写入的内容，调用toString()方法，不包括不会自动换行
	 * @throws IOException
	 *             IO异常
	 */
	public static void write(OutputStream out, String charsetName, boolean isCloseOut, Object... contents)
			throws IOException {

		write(out, Charset.forName(charsetName), isCloseOut, contents);
	}

	/**
	 * 将多部分内容写到流中，自动转换为字符串
	 * 
	 * @param out
	 *            输出流
	 * @param charset
	 *            写出的内容的字符集
	 * @param isCloseOut
	 *            写入完毕是否关闭输出流
	 * @param contents
	 *            写入的内容，调用toString()方法，不包括不会自动换行
	 * @throws IOException
	 *             IO异常
	 * @since 3.0.9
	 */
	public static void write(OutputStream out, Charset charset, boolean isCloseOut, Object... contents)
			throws IOException {

		OutputStreamWriter osw = null;
		try {
			osw = getWriter(out, charset);
			for (Object content : contents) {
				if (content != null) {
					osw.write(String.valueOf(content));
					osw.flush();
				}
			}
		} catch (IOException e) {
			throw new IOException(e);
		} finally {
			if (isCloseOut) {
				close(osw);
			}
		}
	}

	/**
	 * 将多部分内容写到流中
	 * 
	 * @param out
	 *            输出流
	 * @param isCloseOut
	 *            写入完毕是否关闭输出流
	 * @param contents
	 *            写入的内容
	 * @throws IOException
	 *             IO异常
	 */
	public static void write(OutputStream out, boolean isCloseOut, Serializable... contents) throws IOException {

		ObjectOutputStream osw = null;
		try {
			osw = out instanceof ObjectOutputStream ? (ObjectOutputStream) out : new ObjectOutputStream(out);
			for (Object content : contents) {
				if (content != null) {
					osw.writeObject(content);
					osw.flush();
				}
			}
		} catch (IOException e) {
			throw new IOException(e);
		} finally {
			if (isCloseOut) {
				close(osw);
			}
		}
	}

	/**
	 * 将Reader中的内容复制到Writer中 使用默认缓存大小
	 * 
	 * @param reader
	 *            Reader
	 * @param writer
	 *            Writer
	 * @return 拷贝的字节数
	 * @throws IOException
	 *             IO异常
	 */
	public static long copy(Reader reader, Writer writer) throws IOException {

		return copy(reader, writer, DEFAULT_BUFFER_SIZE);
	}

	/**
	 * 将Reader中的内容复制到Writer中
	 * 
	 * @param reader
	 *            Reader
	 * @param writer
	 *            Writer
	 * @param bufferSize
	 *            缓存大小
	 * @return 传输的byte数
	 * @throws IOException
	 *             IO异常
	 */
	public static long copy(Reader reader, Writer writer, int bufferSize) throws IOException {

		char[] buffer = new char[bufferSize];
		long size = 0;
		int readSize;
		while ((readSize = reader.read(buffer, 0, bufferSize)) != EOF) {
			writer.write(buffer, 0, readSize);
			size += readSize;
			writer.flush();
		}
		return size;
	}

	/**
	 * 拷贝流，使用默认Buffer大小
	 * 
	 * @param in
	 *            输入流
	 * @param out
	 *            输出流
	 * @return 传输的byte数
	 * @throws IOException
	 *             IO异常
	 */
	public static long copy(InputStream in, OutputStream out) throws IOException {

		return copy(in, out, DEFAULT_BUFFER_SIZE);
	}

	/**
	 * 拷贝流
	 * 
	 * @param in
	 *            输入流
	 * @param out
	 *            输出流
	 * @param bufferSize
	 *            缓存大小
	 * @return 传输的byte数
	 * @throws IOException
	 *             IO异常
	 */
	public static long copy(InputStream in, OutputStream out, int bufferSize) throws IOException {

		if (bufferSize <= 0) {
			bufferSize = DEFAULT_BUFFER_SIZE;
		}

		byte[] buffer = new byte[bufferSize];
		long size = 0;
		for (int readSize = -1; (readSize = in.read(buffer)) != EOF;) {
			out.write(buffer, 0, readSize);
			size += readSize;
			out.flush();
		}
		return size;
	}

}
